package com.bupt.basic;


import com.bupt.annotation.MParam;
import com.bupt.base.BaseDataSupport;

import com.bupt.dto.network.Node;
import com.bupt.exception.BaseException;
import com.bupt.utils.LocalVerify;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.lang.NonNull;

import java.io.Serializable;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;


/**
 * 基础网络
 * 包含了 节点 链路 以及 其他的基本信息
 * <pre>
 *     @Data 这个注解仅仅是生成了getter and setter 的方法
 * </pre>
 *
 * @author breakpoint/赵先生
 * 2020/09/22
 */
@EqualsAndHashCode
@Data
public final class BasicNetWork  implements IBasicNetWork, Serializable {
    private static final long serialVersionUID = -2689078848951715359L;
    @JsonIgnore
    private String netWorkId; // ID
    @JsonIgnore
    private Date createTime; // 创建的时间

    public BasicNetWork(String netWorkId, Date createTime) {
        this.netWorkId = netWorkId;
        this.createTime = createTime;
    }

    private static final Object lock = new Object(); // 锁信息
    @JsonIgnore
    // ID的生成器
    private final AtomicInteger id_gen = new AtomicInteger(0);
    /* 网络的基本信息  */
    // key:nodeId value:BasicNode
    private Map<String, BasicNode> nodeMap = new HashMap<>();
    // value：nodeName
    @JsonIgnore
    private Set<String> nodeNameSet = new HashSet<>();
    private List<BasicNode> nodeList = new ArrayList<>();
    @JsonIgnore
    private Map<String,List<PortL>> ports=new HashMap<>();
    /**
     * 链路的基本信息操作   等等
     */
    // key: linkId ; value: BasicLink
    @JsonIgnore
    private Map<String, BasicLink> fiberLinkHashMap = new HashMap<>();
    @JsonIgnore
    private Set<String> fiberLinkNameSet = new HashSet<>();// 与上面的同理
    // 链路的基本信息
    private List<BasicLink> fiberLinks = new ArrayList<>();
    // key: linkId ; value: BasicLink
    @JsonIgnore
    private Map<String, BasicLink> wdmLinkHashMap = new HashMap<>();
    @JsonIgnore
    private Set<String> wdmLinkNameSet = new HashSet<>();// 与上面的同理
    // 链路的基本信息
    private List<BasicLink> wdmLinks = new ArrayList<>();
    // key: linkId ; value: BasicLink
    @JsonIgnore
    private Map<String, BasicLink> otnLinkHashMap = new HashMap<>();
    @JsonIgnore
    private Set<String> otnLinkNameSet = new HashSet<>();// 与上面的同理
    // 链路的基本信息
    private List<BasicLink> otnLinks = new ArrayList<>();

    // key: linkId ; value: BasicLink
    @JsonIgnore
    private Map<String, BasicLink> sdhLinkHashMap = new HashMap<>();
    private Set<String> sdhLinkNameSet = new HashSet<>();// 与上面的同理
    @JsonIgnore
    // 链路的基本信息
    private List<BasicLink> sdhLinks = new ArrayList<>();

    // 短波的链路
    @JsonIgnore
    private Map<String, BasicLink> shortWaveLinkHashMap = new HashMap<>();
    @JsonIgnore
    private Set<String> shortWaveLinkNameSet = new HashSet<>();// 与上面的同理
    // 链路的基本信息
    private List<BasicLink> shortWaveLinks = new ArrayList<>();

    // 卫星的链路
    @JsonIgnore
    private Map<String, BasicLink> satelliteLinkHashMap = new HashMap<>();
    @JsonIgnore
    private Set<String> satelliteLinkNameSet = new HashSet<>();// 与上面的同理
    // 链路的基本信息
    private List<BasicLink> satelliteLinks = new ArrayList<>();

    // 代码的名字
    @JsonIgnore
    private Set<String> codeNameSet = new HashSet<>();


    // 检查当前的网络情况
    public void checkCurrentNetWork() {
            if (null == this.nodeMap) this.nodeMap = new HashMap<>();
            if (null == this.nodeNameSet) this.nodeNameSet = new HashSet<>();
            if (null == this.nodeList) this.nodeList = new ArrayList<>();

            if (null == this.fiberLinkHashMap) this.fiberLinkHashMap = new HashMap<>();
            if (null == this.fiberLinkNameSet) this.fiberLinkNameSet = new HashSet<>();// 与上面的同理
            if (null == this.fiberLinks) this.fiberLinks = new ArrayList<>();

            if (null == this.wdmLinkHashMap) this.wdmLinkHashMap = new HashMap<>();
            if (null == this.wdmLinkNameSet) this.wdmLinkNameSet = new HashSet<>();// 与上面的同理
            if (null == this.wdmLinks) this.wdmLinks = new ArrayList<>();

            if (null == this.otnLinkHashMap) this.otnLinkHashMap = new HashMap<>();
            if (null == this.otnLinkNameSet) this.otnLinkNameSet = new HashSet<>();// 与上面的同理
            if (null == this.otnLinks) this.otnLinks = new ArrayList<>();

            if (null == this.sdhLinkHashMap) this.sdhLinkHashMap = new HashMap<>();
            if (null == this.sdhLinkNameSet) this.sdhLinkNameSet = new HashSet<>();// 与上面的同理
            if (null == this.sdhLinks) this.sdhLinks = new ArrayList<>();

            if (null == this.shortWaveLinkHashMap) this.shortWaveLinkHashMap = new HashMap<>();
            if (null == this.shortWaveLinkNameSet) this.shortWaveLinkNameSet = new HashSet<>();// 与上面的同理
            if (null == this.shortWaveLinks) this.shortWaveLinks = new ArrayList<>();

            if (null == this.satelliteLinkHashMap) this.satelliteLinkHashMap = new HashMap<>();
            if (null == this.satelliteLinkNameSet) this.satelliteLinkNameSet = new HashSet<>();// 与上面的同理
            if (null == this.satelliteLinks) this.satelliteLinks = new ArrayList<>();
            if (null == this.codeNameSet) this.codeNameSet = new HashSet<>();

    }
    // 获取层次的链路
    @NonNull
    public List<BasicLink> getBasicLinksByLayer(@MParam("链路的层次") LayerEnum layer) throws BaseException {
        synchronized (lock) {
            //checkCurrentNetWork();
            switch (layer) {
                case FIBER: { // FiberLink
                    return this.fiberLinks;
                }
                case WDM: { // WdmLink
                    return this.wdmLinks;
                }
                case OTN: { // OTNLink
                    return this.otnLinks;
                }
                case SDH: { // SDHLink
                    return this.sdhLinks;
                }
                case SATELLITE: { // SATELLITE
                    return this.satelliteLinks;
                }
                case SHORTWAVE: { // SHORTWAVE
                    return this.shortWaveLinks;
                }
                default: {
                    throw new BaseException("输入的layer不正确");
                }
            } // end switch
        }
    }

    // 获取层次的链路 Map
    public Map<String, BasicLink> getBasicLinkMapByLayer(@MParam("链路的层次") LayerEnum layer) throws BaseException {
        synchronized (lock) {
           // checkCurrentNetWork();
            switch (layer) {
                case FIBER: { // FiberLink
                    return this.fiberLinkHashMap;
                }
                case WDM: { // WdmLink
                    return this.wdmLinkHashMap;
                }
                case OTN: { // OTNLink
                    return this.otnLinkHashMap;
                }
                case SDH: { // SDHLink
                    return this.sdhLinkHashMap;
                }
                default: {
                    throw new BaseException("输入的layer不正确");
                }
            } // end switch
        }
    }

    // 获取层次的链路 nameSet
    public Set<String> getBasicLinkNameSetByLayer(@MParam("链路的层次") LayerEnum layer) throws BaseException {
        synchronized (lock) {
            //checkCurrentNetWork();
            switch (layer) {
                case FIBER: { // FiberLink
                    return this.fiberLinkNameSet;
                }
                case WDM: { // WdmLink
                    return this.wdmLinkNameSet;
                }
                case OTN: { // OTNLink
                    return this.otnLinkNameSet;
                }
                case SDH: { // SDHLink
                    return this.sdhLinkNameSet;
                }
                case SATELLITE: { // SATELLITE
                    return this.satelliteLinkNameSet;
                }
                case SHORTWAVE: { // SHORTWAVE
                    return this.shortWaveLinkNameSet;
                }
                default: {
                    throw new BaseException("输入的layer不正确");
                }
            } // end switch
        }
    }

    // 查看某一个节点是否含有link的操作
    public boolean theNodeIsHaveLinks(@MParam("需要校验的节点信息") BasicNode basicNode) throws BaseException {
        synchronized (lock) {
           // checkCurrentNetWork();
            if (null == basicNode) throw new BaseException("查看的节点 null");
            if (null != this.nodeNameSet && this.nodeNameSet.contains(basicNode.getName())) {
                if (null != fiberLinks && fiberLinks.size() > 0) {
                    for (BasicLink link : fiberLinks) {
                        if (link.getNodeHead().equals(basicNode.getNodeId())
                                || link.getNodeTail().equals(basicNode.getNodeId()))
                            return true;
                    }
                }
            }
            return false;
        }
    }

    // 查看某一个节点是否含有link的操作
    public boolean theNodeIsHaveLinks(@MParam("nodeId") String nodeId) throws BaseException {
        synchronized (lock) {
           // checkCurrentNetWork();
            if (null != nodeMap) {
                BasicNode node = this.nodeMap.get(nodeId);
                if (null == node) throw new BaseException("查看的节点不存在" + nodeId);
                return this.theNodeIsHaveLinks(node);
            } else {
                return false;
            }
        }
    }



    // 获取唯一的名字的信息
    @Deprecated
    private String getUniqueLinkName(@MParam("原始的名字") String originName, LayerEnum layer) throws BaseException {
        synchronized (lock) {
           // checkCurrentNetWork();
            Set<String> nameSet = this.getBasicLinkNameSetByLayer(layer);
            if (!nameSet.contains(originName)) return originName;
            String res = null;
            do {
                res = originName + "_" + id_gen.getAndIncrement();
            } while (nameSet.contains(res));
            return res;
        }
    }



    // 用于快速的查看是哪一种类型的操作 dict
    public static final Map<Class<?>, LayerEnum> clazzToIntegerMap = new HashMap<Class<?>, LayerEnum>();

    static {
        // 静态代码块的操作
        clazzToIntegerMap.put(FiberLink.class, LayerEnum.FIBER);
        clazzToIntegerMap.put(WdmLink.class, LayerEnum.WDM);
        clazzToIntegerMap.put(OtnLink.class, LayerEnum.OTN);
        clazzToIntegerMap.put(SdhLink.class, LayerEnum.SDH);
       /* clazzToIntegerMap.put(SatelliteLink.class, LayerEnum.SATELLITE);
        clazzToIntegerMap.put(ShortWaveLink.class, LayerEnum.SHORTWAVE);*/
    }

    // 更新list 里面的节点的数据
    private void updateNodeList(List<BasicNode> nodes, BasicNode sourceNode) {
        if (null != nodes && nodes.size() > 0) {
            for (BasicNode node : nodes) {
                if (node.getNodeId().equals(sourceNode.getNodeId())) {
                    node.updateSelf(sourceNode);
                    break;
                }
            }
        }
    }

    // 更新一个节点的操作
    public boolean updateNode(BasicNode basicNode) throws BaseException {
        synchronized (lock) {
           // this.checkCurrentNetWork();
            // # issue 更新节点数据时候节点的代码是否可以更新
            // 获取节点操作
            BasicNode node = this.nodeMap.get(basicNode.getNodeId());
            if (null == node) throw new BaseException("没有该节点，无法更新");
            // # issue 节点代码的更新问题
            this.codeNameSet.remove(node.getCode());
            // # 链路代码的问题
            if (this.codeNameSet.contains(basicNode.getCode())) {
                // 加入以前移除的名字 节点的代码
                this.codeNameSet.add(node.getCode());
                throw new BaseException("节点代码重复");
            } else {
                // 添加新的信息
                this.codeNameSet.add(basicNode.getCode());
            }
            // 先进行移除的操作
            this.nodeNameSet.remove(node.getName());
            // 添加的判断
            if (this.nodeNameSet.add(basicNode.getName())) {
                // 更新自己的操作
                node.updateSelf(basicNode);
                updateNodeList(this.nodeList, basicNode);
            } else {
                // 回滚节点的名字
                this.nodeNameSet.add(node.getName());

                // 移除加入的 加入原始的 保持 没有问题
                this.codeNameSet.remove(basicNode.getCode());
                this.codeNameSet.add(node.getCode());

                throw new BaseException("节点的名称重复");
            }
            return true;
        }
    }

    // 移除一个节点的操作
    public BasicNode removeNode(String nodeId) throws BaseException {
        BasicNode node = this.nodeMap.get(nodeId);
        if (null == node) throw new BaseException("移除节点不存在");
        return this.removeNode(node);
    }

    public BasicNode removeNode(BasicNode basicNode) throws BaseException {
        synchronized (lock) {
            //checkCurrentNetWork();
            LocalVerify.verifyObject(basicNode, "basicNode");
            BasicNode res = null;
            if (this.nodeNameSet.remove(basicNode.getName())) {
                // 移除code 的操作 保证代码的正确执行吧
                this.codeNameSet.remove(basicNode.getCode());
                res = this.nodeMap.remove(basicNode.getNodeId());
                // 移除这个节点信息
                Iterator<BasicNode> iterator = this.nodeList.iterator();
                while (iterator.hasNext()) {
                    BasicNode next = iterator.next();
                    if (next.getNodeId().equals(basicNode.getNodeId())) {
                        iterator.remove();// 移除的元素的操作
                        break;
                    }
                }
            }
            return res;
        }
    }

    // 添加节点的操作
    public boolean addNode(BasicNode basicNode) throws BaseException {
        synchronized (lock) {
            //checkCurrentNetWork();
            LocalVerify.verifyObject(basicNode, "basicNode");
            // # issue 节点代码的问题
            if (this.codeNameSet.contains(basicNode.getCode()))
                throw new BaseException("节点代码重复");

            if (this.nodeNameSet.add(basicNode.getName())) {
                // # 添加节点的代码
                this.codeNameSet.add(basicNode.getCode());
                // 名字检验
                if (null == this.nodeMap.put(basicNode.getNodeId(), basicNode)) { //
                    this.nodeList.add(basicNode);
                    return true;
                }
            } else {
                // 移除添加好的code 防止 出现问题
                this.codeNameSet.remove(basicNode.getCode());
                throw new BaseException("节点的名字重复：" + basicNode.getName());
            }
            return false;
        }
    }


    //  更新一条链路的操作
    public boolean updateLink(BasicLink link) throws BaseException {
        synchronized (lock) {
           // checkCurrentNetWork();
            // 校验基本信息
            LocalVerify.verifyObject(link, link.getClass().getName());
            // 获取层次的信息
            LayerEnum layer = clazzToIntegerMap.get(link.getClass());
            if (null == layer) {
                throw new BaseException("该链路类型不能进行与移除" + link.getClass().getName());
            }
            // 设置子粒度的数目
            switch (layer) {
                case WDM: {
                    WdmLink wdmLink = (WdmLink) link;
                    // 设置子粒度的数目
                    wdmLink.setSize(wdmLink.getSize());
                    break;
                }
                case OTN: {
                    OtnLink otnLink = (OtnLink) link;
                    // 设置子粒度的数目
                    otnLink.setSize(BaseDataSupport.getOTNSlotNumByRateStr(otnLink.getRateStr()));
                    break;
                }
                case SDH: {
                    SdhLink sdhLink = (SdhLink) link;
                    // 设置子粒度
                    sdhLink.setSize(BaseDataSupport.getSdhSlotNumByRateStr(sdhLink.getRateStr()));
                    break;
                }
            }
            // 获取到原来的链路的信息
            Map<String, BasicLink> basicLinkMap = this.getBasicLinkMapByLayer(layer);
            // 目标的链路信息
            BasicLink targetLink = basicLinkMap.get(link.getId());
            if (null == targetLink) throw new BaseException("不存在该链路，更新失败");
            // # issue 链路代码的更新问题
            this.codeNameSet.remove(targetLink.getCode());
            // # 链路代码的问题
            if (this.codeNameSet.contains(link.getCode())) {
                // 加入以前移除的名字 链路的代码
                this.codeNameSet.add(targetLink.getCode());
                throw new BaseException("节点代码重复");
            } else {
                // 增加新的链路的代码
                this.codeNameSet.add(link.getCode());
            }
            Set<String> basicLinkNameSet = this.getBasicLinkNameSetByLayer(layer);
            // 移除以前的链路的名字
            basicLinkNameSet.remove(targetLink.getName());
            if (basicLinkNameSet.contains(link.getName())) {
                // 存在新增加的名字 那么就应当回滚当前的名字
                basicLinkNameSet.add(targetLink.getName());

                // 回滚 code的列表
                this.codeNameSet.remove(link.getCode());
                this.codeNameSet.add(targetLink.getCode());

                throw new BaseException("链路名称已存在 " + link.getName());
            } else {
                // 原来不包含的情况
                basicLinkNameSet.add(link.getName());
                IBasicNetWork.updateLinkFields(targetLink, link, layer);
                List<BasicLink> links = this.getBasicLinksByLayer(layer);
                if (null != links && links.size() > 0) {
                    for (BasicLink target : links) {
                        if (target.getId().equals(link.getId())) {
                            IBasicNetWork.updateLinkFields(target, link, layer);
                            break;
                        }
                    }
                }
            }// end else
            return true;
        }
    } // end method

    // 公共的移除元素
    private void removeFromIterator(@MParam("Iterator") Iterator<BasicLink> iterator,
                                    @MParam("linkId") String linkId) {
        synchronized (lock) {
           // checkCurrentNetWork();
            while (iterator.hasNext()) {
                BasicLink next = iterator.next();
                if (next.getId().equals(linkId)) {
                    iterator.remove();
                    break;
                }
            } // end while
        }
    } // end removeFromIterator

    // 移除一条链路的操作
    public List<BasicLink> removeLink(Project project,String linkId, LayerEnum layer) throws BaseException {
        // 删除链路的信息
        Map<String, BasicLink> basicLinkMapByLayer = this.getBasicLinkMapByLayer(layer);
        BasicLink link = basicLinkMapByLayer.get(linkId);
        if (null == link) throw new BaseException("链路不存在 linkId" + linkId);
        return this.removeLink(link);
    }

    // 移除一条链路
    @NonNull
    public List<BasicLink> removeLink(@MParam("网络的链路") BasicLink link) throws BaseException {
        synchronized (lock) {
           // checkCurrentNetWork();
            if (null == link) throw new BaseException("链路不能为空");
            LayerEnum type = clazzToIntegerMap.get(link.getClass());
            if (null == type) {
                throw new BaseException("该链路类型不能进行与移除" + link.getClass().getName());
            }
            List<BasicLink> res = new ArrayList<>();
            // 根据不同的层次添加链路
            switch (type) {
                case FIBER: { // FiberLink
                    if (this.fiberLinkNameSet.remove(link.getName())) { // 校验是否存在 之后在进行移除的操作
                        this.fiberLinkHashMap.remove(link.getId());
                        //// 移除本身
                        removeFromIterator(this.fiberLinks.iterator(), link.getId());
                        res.add(link);
                        this.codeNameSet.remove(link.getCode());
                        // 首先要移除 下层的 之后 要移除上层的链路的 链路
                        // 移除的信息是 Fiber 层上的
                        //this.removeAllLoadInLinkIdsByLayerAndLink(LayerEnum.FIBER, link); // 没有下层了 仅仅移除上层就可以了
                        // 移除上层的链路
                        res.addAll(this.removeLinkByOriginalLayer(link, LayerEnum.FIBER));
                    }
                    break;
                }
                case WDM: { // WdmLink
                    if (this.wdmLinkNameSet.remove(link.getName())) { // 校验是否存在 之后在进行移除的操作
                        this.wdmLinkHashMap.remove(link.getId());
                        removeFromIterator(this.wdmLinks.iterator(), link.getId());
                        res.add(link);
                        this.codeNameSet.remove(link.getCode());
                        // 首先要移除 下层的 之后 要移除上层的链路的 链路
                        // 移除的信息是 Fiber 层上的
                        this.removeAllLoadInLinkIdsByLayerAndLink(LayerEnum.FIBER, link);
                        res.addAll(this.removeLinkByOriginalLayer(link, LayerEnum.WDM));
                    }
                    break;
                }
                case OTN: { // OTNLink
                    if (this.otnLinkNameSet.remove(link.getName())) { // 校验是否存在 之后在进行移除的操作

                        this.otnLinkHashMap.remove(link.getId());
                        removeFromIterator(this.otnLinks.iterator(), link.getId());
                        res.add(link);
                        this.codeNameSet.remove(link.getCode());
                        // 首先要移除 下层的 之后 要移除上层的链路的 链路
                        // 移除的信息是 Fiber 层上的
                        this.removeAllLoadInLinkIdsByLayerAndLink(LayerEnum.FIBER, link);
                        res.addAll(this.removeLinkByOriginalLayer(link, LayerEnum.OTN));
                    }
                    break;
                }
                case SDH: { // SDHLink
                    if (this.sdhLinkNameSet.remove(link.getName())) { // 校验是否存在 之后在进行移除的操作

                        this.sdhLinkHashMap.remove(link.getId());
                        removeFromIterator(this.sdhLinks.iterator(), link.getId()); // 移除这条链路的操作
                        res.add(link);
                        this.codeNameSet.remove(link.getCode());
                        //  删除下层含有的id
                        SdhLink sdhLink = (SdhLink) link;
                        LayerEnum layerEnum = LayerEnum.getLayerEnum(sdhLink.getLoadOnLayer());
                        if (null == layerEnum) throw new BaseException("WDM or OTN for 承载层");
                        // 移除下层 链路的 上面 标记的 linkIDs
                        this.removeAllLoadInLinkIdsByLayerAndLink(layerEnum, link);
                        // 由于 目前SDH的最高的层级 所以删除的时候 可以直接删除的 不用做其他的任何的操作
                    }
                    break;
                }
                /*  短波 与 卫星  的移除工作比较简单 仅仅是 移除就可以了    */
                case SATELLITE: {
                    // 卫星的操作
                    if (this.satelliteLinkNameSet.remove(link.getName())) { // 校验是否存在 之后在进行移除的操作
                        this.satelliteLinkHashMap.remove(link.getId());
                        removeFromIterator(this.satelliteLinks.iterator(), link.getId()); // 移除这条链路的操作
                        res.add(link);
                        this.codeNameSet.remove(link.getCode());
                    }
                    break;
                }
                case SHORTWAVE: {
                    // 短波操作
                    if (this.shortWaveLinkNameSet.remove(link.getName())) { // 校验是否存在 之后在进行移除的操作
                        this.shortWaveLinkHashMap.remove(link.getId());
                        removeFromIterator(this.shortWaveLinks.iterator(), link.getId()); // 移除这条链路的操作
                        res.add(link);
                        this.codeNameSet.remove(link.getCode());
                    }
                    break;
                }
            } // end switch
            return res;
        }
    }

    //  1. 移除上层的链路操作 盲猜 现在是递归的问题了
    //  2. 首先获取到所有的承载在该链路上的上层链路 是进行重新规划或者是直接删除的操作
    private List<BasicLink> removeLinkByOriginalLayer(@MParam("待移除链路信息") BasicLink link,
                                                      @MParam("承载层信息") LayerEnum originalLayer) throws BaseException {
        synchronized (lock) {
           // checkCurrentNetWork();
            List<BasicLink> res = new ArrayList<>();
            // 获取到承载该链路上的所有的上层链路
            List<UpLevelMsg> loadInLinkIds = link.getLoadInLinkIds();
            // 查看是否含有链路的IDs
            if (null != loadInLinkIds && loadInLinkIds.size() > 0) {
                // 循环遍历上面的链路 查找层次信息
                for (UpLevelMsg upLevelMsg : loadInLinkIds) {
                    // 由于当前的网络是可以已经是修改后的网络，所以 我们可以根据当前的网络判断这条的路径是否还有其他的路径
                    LayerEnum targetLayer = LayerEnum.getLayerEnum(upLevelMsg.getLevel());// 链路的当前的层次
                    Map<String, BasicLink> basicLinkMapByLayer = this.getBasicLinkMapByLayer(targetLayer);
                    // 获取到上层的链路的信息
                    BasicLink upLink = basicLinkMapByLayer.get(upLevelMsg.getLinkId());
                    if (null != upLink) {
                        // 就如前面所说的 已经 移除了本层的链路 计算当前的网络是否还会有链路的信息，
                        // 如果有的话，就会进行重新的规划，没有的话，那么就进行递归的删除
                        List<BasicLink> basicLinks =
                                BasicNetWorkUtil.calculatePathLinksByDAlgorithm(this, upLink.getNodeHead(),
                                        upLink.getNodeTail(), originalLayer);
                        if (basicLinks.size() > 0) {
                            // 重新分配这条链路
                            upLink.getLoadOnLinksIds().clear();
                            this.removeAllLoadInLinkIdsByLayerAndLink(originalLayer, upLink);
                            for (BasicLink basicLink : basicLinks) {
                                // 承载层加入需要 承载的链路
                                basicLink.getLoadInLinkIds().add(new UpLevelMsg(targetLayer.getLayer(), link.getId()));
                                // 设置需要承载的下层链路
                                upLink.getLoadOnLinksIds().add(basicLink.getId());
                            }
                        } else {
                            // 如果分配失败的情形要递归删除
                            res.addAll(this.removeLink(upLink));
                        }
                    }
                }
            } // end
            return res;
        }
    } // end removeLinkByTargetLayer

    // 根据层次以及其他的信息 移除掉 下一层的 链路上 所承载的 上层的链路的ID
    private void removeAllLoadInLinkIdsByLayerAndLink(@MParam("层次信息") LayerEnum layerEnum,
                                                      @MParam("链路信息") BasicLink link)
            throws BaseException {
        synchronized (lock) {
            //checkCurrentNetWork();
            // 获取到可以操作的链路
            Map<String, BasicLink> basicLinkMapByLayer = getBasicLinkMapByLayer(layerEnum);
            List<String> loadOnLinksIds = link.getLoadOnLinksIds();
            for (String linkId : loadOnLinksIds) {
                // 获取到所在层的链路里面所承载的上层的链路的信息
                BasicLink currentLink = basicLinkMapByLayer.get(linkId);
                if (null != currentLink) {
                    List<UpLevelMsg> loadInLinkIds = currentLink.getLoadInLinkIds();
                    Iterator<UpLevelMsg> iterator = loadInLinkIds.iterator();
                    while (iterator.hasNext()) { // 循环读取 以及删除对应的下层的链路信息
                        UpLevelMsg next = iterator.next();
                        if (next.getLinkId().equals(link.getId())) {
                            iterator.remove();
                            break;
                        }
                    }// while
                }
            }
        }
    }

    // 添加一条链路的操作
    public boolean addLink(@MParam("网络的链路") BasicLink link)
            throws BaseException {
        synchronized (lock) {
            // 校验当前的网络信息是否正确
          //  this.checkCurrentNetWork();
            // 校验对象是都是空
            LocalVerify.verifyObject(link, link.getClass().getName());
            // # 链路代码的问题
            if (this.codeNameSet.contains(link.getCode())) {
                log.warn("链路代码重复【{}】", link.getName());
                throw new BaseException("链路代码重复【" + link.getName() + "】");
            }
            // 添加我们的CODE
            this.codeNameSet.add(link.getCode());
            // 获取层次的信息
            LayerEnum type = clazzToIntegerMap.get(link.getClass());
            if (null == type) {
                throw new BaseException("该链路类型不能进行添加到当前的网络" + link.getClass().getName());
            }
            //检验是否有端点
            BasicNode nodeHead = this.nodeMap.get(link.getNodeHead());
            BasicNode nodeTail = this.nodeMap.get(link.getNodeTail());
            if (null == nodeHead || null == nodeTail) throw new BaseException("您提交的链路含有不存在的节点");
            link.setNodeHeadName(nodeHead.getName());
            link.setNodeTailName(nodeTail.getName());

            boolean isThrowTag = false;// 是否抛出异常
            switch (type) {
                case FIBER: { // FiberLink
                    if (this.fiberLinkNameSet.add(link.getName())) {
                        if (null == this.fiberLinkHashMap.put(link.getId(), link)) {
                            this.fiberLinks.add(link);
                        }
                    } else {
                        isThrowTag = true;
                    }
                    break;
                }
                case WDM: { // WdmLink
                    if (this.wdmLinkNameSet.add(link.getName())) {
                        WdmLink wdmLink = (WdmLink) link;
                        try {
                            LayerEnum layer = LayerEnum.FIBER;
                            /*
                                新增操作 应景涛 要求进行更改
                             */
                            List<BasicLink> links = this.getBasicLinksByLayer(layer);
                            List<BasicNode> nodeList = this.getNodeList();
                            Map<String, BasicNode> nodeMap = this.getNodeMap();
                            // 计算承载的链路
                            List<BasicLink> pathLinks = BasicNetWorkUtil.findPathLinks(links, nodeList, nodeMap, nodeHead, nodeTail, link.rate);
                            // 校验
                            if (null == pathLinks || pathLinks.size() == 0) throw new BaseException("没有找到承载的链路");
                            // 设置 fiberLinkIds
                            final List<String> fiberLinkIds = new ArrayList<>();
                            // 获取到响应的链路
                            pathLinks.forEach(pathLink -> fiberLinkIds.add(pathLink.getId()));
                            this.addFiberLinkIds(link, fiberLinkIds);

                            // 计算所需要的路径 是否满足 我们的 承载的要求
//                            List<BasicLink> list = BasicNetWorkUtil.calculatePathLinksByDAlgorithm(this,
//                                    nodeHead.nodeId, nodeTail.nodeId, layer);
                            // 增加承载的信息
                            if (pathLinks.size() > 0) {
                                if (null == this.wdmLinkHashMap.put(link.getId(), link)) {
                                    //添加链路
                                    this.wdmLinks.add(link);
                                }
                                wdmLink.setLayerRouteLinkList(pathLinks);
                                wdmLink.setBaseLinks(pathLinks);

                                for (BasicLink basicLink : pathLinks) {
                                    basicLink.getLoadInLinkIds().add(new UpLevelMsg(LayerEnum.WDM.getLayer(),
                                            link.getId())); // 承载层加入需要 承载的链路
                                    link.getLoadOnLinksIds().add(basicLink.getId());// 设置需要承载的下层链路
                                }
                            } else {
                                // 由于需要 承载的 链路不联通 所以 要取消 这条 链路
                                this.wdmLinkNameSet.remove(link.getName()); // 移除所添加的链路信息
                                throw new BaseException("没有有效的承载链路");
                            }
                        } catch (Exception e) {
                            this.wdmLinkNameSet.remove(link.getName()); // 移除所添加的链路信息
                            this.wdmLinkHashMap.remove(link.getId());
                            this.removeFromIterator(this.wdmLinks.iterator(), link.getId());
                            throw new BaseException(e.getMessage());
                        }


                    } else {
                        isThrowTag = true;
                    }
                    break;
                }
                case OTN: { // OTNLink
                    if (this.otnLinkNameSet.add(link.getName())) {
                        OtnLink otnLink = (OtnLink) link;
                        try {
                            LayerEnum layer = LayerEnum.getLayerEnum(otnLink.getLoadOnLayer());
                            /*
                                新增操作 应景涛 要求进行更改
                             */
                            List<BasicLink> links = this.getBasicLinksByLayer(layer);
                            List<BasicNode> nodeList = this.getNodeList();
                            Map<String, BasicNode> nodeMap = this.getNodeMap();
                            // 计算承载的链路
                            List<BasicLink> pathLinks = BasicNetWorkUtil.findPathLinks(links, nodeList, nodeMap, nodeHead, nodeTail, link.rate);
                            // 校验
                            if (null == pathLinks || pathLinks.size() == 0) throw new BaseException("没有找到承载的链路");
                            // 设置 fiberLinkIds
                            for (BasicLink pathLink : pathLinks) {
                                this.addFiberLinkIds(link, pathLink.getFiberLinkIdSet());
                            }
                            // 计算所需要的路径 是否满足 我们的 承载的要求
                        /*    List<BasicLink> list = BasicNetWorkUtil.calculatePathLinksByDAlgorithm(this,
                                    nodeHead.getNodeId(), nodeTail.getNodeId(), layerEnum);*/
                            if (pathLinks.size() > 0) {
                                if (null == this.otnLinkHashMap.put(link.getId(), link)) {
                                    //添加链路
                                    this.otnLinks.add(link);
                                }
                                otnLink.setLayerRouteLinkList(pathLinks);
                                otnLink.setBaseLinks(pathLinks);
                                for (BasicLink basicLink : pathLinks) {
                                    basicLink.getLoadInLinkIds().add(new UpLevelMsg(LayerEnum.OTN.getLayer(), link.getId())); // 承载层加入需要 承载的链路
                                    link.getLoadOnLinksIds().add(basicLink.getId());// 设置需要承载的下层链路
                                }
                            } else {
                                // 由于需要 承载的 链路不联通 所以 要取消 这条 链路
                                this.otnLinkNameSet.remove(link.getName()); // 移除所添加的链路信息
                                throw new BaseException("没有有效的承载链路");
                            }
                        } catch (Exception e) {
                            this.otnLinkNameSet.remove(link.getName()); // 移除所添加的链路信息
                            this.otnLinkHashMap.remove(link.getId());
                            this.removeFromIterator(this.otnLinks.iterator(), link.getId());
                            throw new BaseException(e.getMessage());
                        }

                    } else {
                        isThrowTag = true;
                    }
                    break;
                }
                case SDH: { // SDHLink
                    if (this.sdhLinkNameSet.add(link.getName())) {
                        SdhLink sdhLink = (SdhLink) link;
                        try {
                            LayerEnum layer = LayerEnum.getLayerEnum(sdhLink.getLoadOnLayer());
                            /*
                                新增操作 应景涛 要求进行更改
                             */
                            List<BasicLink> links = this.getBasicLinksByLayer(layer);
                            List<BasicNode> nodeList = this.getNodeList();
                            Map<String, BasicNode> nodeMap = this.getNodeMap();
                            // 计算承载的链路
                            List<BasicLink> pathLinks = BasicNetWorkUtil.findPathLinks(links, nodeList, nodeMap, nodeHead, nodeTail, link.rate);
                            // 校验
                            if (null == pathLinks || pathLinks.size() == 0) throw new BaseException("没有找到承载的链路");
                            // 设置 fiberLinkIds
                            for (BasicLink pathLink : pathLinks) {
                                this.addFiberLinkIds(link, pathLink.getFiberLinkIdSet());
                            }

//                            List<BasicLink> list = BasicNetWorkUtil.calculatePathLinksByDAlgorithm(this,
//                                    nodeHead.nodeId, nodeTail.nodeId, layerEnum);
                            if (pathLinks.size() > 0) {
                                if (null == this.sdhLinkHashMap.put(link.getId(), link)) {
                                    //添加链路
                                    this.sdhLinks.add(link);
                                }
                                sdhLink.setLayerRouteLinkList(pathLinks);
                                sdhLink.setBaseLinks(pathLinks);
                                for (BasicLink basicLink : pathLinks) {
                                    basicLink.getLoadInLinkIds().add(new UpLevelMsg(LayerEnum.SDH.getLayer(), link.getId())); // 承载层加入需要 承载的链路
                                    link.getLoadOnLinksIds().add(basicLink.getId());// 设置需要承载的下层链路
                                }
                            } else {
                                // 由于需要 承载的 链路不联通 所以 要取消 这条 链路
                                this.sdhLinkNameSet.remove(link.getName()); // 移除所添加的链路信息
                                throw new BaseException("没有有效的承载链路");
                            }
                        } catch (BaseException e) {
                            this.sdhLinkNameSet.remove(link.getName()); // 移除所添加的链路信息
                            this.sdhLinkHashMap.remove(link.getId());
                            this.removeFromIterator(this.sdhLinks.iterator(), link.getId());
                            throw new BaseException(e.getMessage());
                        }
                    } else {
                        isThrowTag = true;
                    }
                    break;
                }
                /*  其他的操作   */
                case SATELLITE: {
                    // 卫星的操作
                    if (this.satelliteLinkNameSet.add(link.getName())) { // 校验是否存在 之后在进行移除的操作
                        if (null == this.satelliteLinkHashMap.put(link.getId(), link)) {
                            this.satelliteLinks.add(link);
                        }
                    } else {
                        isThrowTag = true;
                    }
                    break;
                }
                case SHORTWAVE: {
                    // 短波操作
                    if (this.shortWaveLinkNameSet.add(link.getName())) { // 校验是否存在 之后在进行移除的操作
                        if (null == this.shortWaveLinkHashMap.put(link.getId(), link)) {
                            this.shortWaveLinks.add(link);
                        }
                    } else {
                        isThrowTag = true;
                    }
                    break;
                }
            } // end switch
            if (isThrowTag) throw new BaseException("链路名字重复"); // throw a exception
            return true; // return ok
        }
    }

    // 添加一个信息到我们的链路上
    public void addService(@MParam("项目的ID") String pId, @MParam("项目的名字") String pName,
                           @MParam("业务的创建人") String demandUserName,
                           @MParam("业务信息") DemandReportService service,
                           @MParam("链路的ID") String linkId, @MParam("层次信息") String layer) throws BaseException {
        synchronized (lock) {
            // 检查当前的网络
           // checkCurrentNetWork();
            List<BasicLink> links = this.getBasicLinksByLayer(LayerEnum.getLayerEnum(layer));
            Map<String, BasicLink> linkMap = this.getBasicLinkMapByLayer(LayerEnum.getLayerEnum(layer));
            // 获取ID
            BasicLink targetLink = linkMap.get(linkId);
            if (null == targetLink) throw new BaseException("该链路不存在");
            targetLink.addService(pId, pName, demandUserName, service);
            for (BasicLink link : links) {
                if (link.getId().equals(linkId)) {
                    link.addService(pId, pName, demandUserName, service);
                    break;
                }
            }
        }
    }

    // 移除所有的业务信息
    public void clearAllService(String linkId, String layer) throws BaseException {
        synchronized (lock) {
            // 检查当前的网络
          //  checkCurrentNetWork();
            List<BasicLink> links = this.getBasicLinksByLayer(LayerEnum.getLayerEnum(layer));
            Map<String, BasicLink> linkMap = this.getBasicLinkMapByLayer(LayerEnum.getLayerEnum(layer));
            // 获取ID
            BasicLink targetLink = linkMap.get(linkId);
            if (null == targetLink) throw new BaseException("该链路不存在");
            targetLink.clearAllService();
            for (BasicLink link : links) {
                if (link.getId().equals(linkId)) {
                    link.clearAllService();
                    break;
                }
            }
        }
    }

    // 从一个网络里面获取到节点的ID
    public String getNodeId(String originalMsg) throws BaseException {
        synchronized (lock) {
            Map<String, BasicNode> nodeMap = this.getNodeMap();
            if (null == nodeMap) throw new BaseException("当前网络中不包含这个节点");
            if (nodeMap.containsKey(originalMsg)) {
                // 说明传入进来的是ID
                return originalMsg;
            } else {
                // 说明传入进来的是name
                Set<String> nodeNameSet = this.getNodeNameSet();
                if (null == nodeNameSet || !nodeNameSet.contains(originalMsg)) {
                    throw new BaseException("当前网络中不包含【" + originalMsg + "】节点");
                }
                List<BasicNode> nodeList = this.getNodeList();
                if (null != nodeList && nodeList.size() > 0) {
                    for (BasicNode node : nodeList) {
                        if (originalMsg.equals(node.getName())) return node.getNodeId();
                    }
                }
            }
        }
        throw new BaseException("当前网络中不包含这个节点");
    }


    // 获取名字
    public String getNodeName(String nodeId) throws BaseException {
        synchronized (lock) {
           // this.checkCurrentNetWork();
            Map<String, BasicNode> nodeMap = this.getNodeMap();
            if (null == nodeMap) throw new BaseException("当前网络中不包含这个节点");
            BasicNode node = nodeMap.get(nodeId);
            if (null == node) throw new BaseException("当前网络中不包含这个节点");
            return node.getName();
        }
    }

    // 景涛需要的接口 用于存储层间路由结果
    public void addFiberLinkIds(BasicLink sourceLink, String[] fiberLinkIdIds) throws BaseException {
        LocalVerify.verifyObject(sourceLink, "链路信息不能为空");
        if (null == fiberLinkIdIds || fiberLinkIdIds.length == 0) {
            throw new BaseException("链路ID不能为空");
        }
        this.addFiberLinkIds(sourceLink, Arrays.asList(fiberLinkIdIds));
    }

    // 景涛需要的接口 用于存储层间路由结果
    // #issue:中心库创建otn链路，承载层为fiber，出现问题 #55
    public void addFiberLinkIds(BasicLink sourceLink, Collection<String> fiberLinkIdIds) throws BaseException {
        LocalVerify.verifyObject(sourceLink, "链路信息不能为空");
        if (null != fiberLinkIdIds && fiberLinkIdIds.size() > 0) {
            // 直接判断就好 以前的方式没有任何的意义
            // 获取到原来的信息
            Set<String> fiberLinkIdSet = sourceLink.getFiberLinkIdSet();
            if (null == fiberLinkIdSet) fiberLinkIdSet = new HashSet<>();
            fiberLinkIdSet.addAll(new ArrayList<>(fiberLinkIdIds));
            sourceLink.setFiberLinkIdSet(fiberLinkIdSet);
        }
    }

    // 清理全网的信息
    public void clearCurNetWorkFiberLinkIds() throws BaseException {
        synchronized (lock) {
           // this.checkCurrentNetWork();
            for (LayerEnum layer : IBasicNetWork.layers) {
                // 获取到相关的链路信息
                List<BasicLink> links = this.getBasicLinksByLayer(layer);
                Map<String, BasicLink> linkMap = this.getBasicLinkMapByLayer(layer);
                // 清理信息
                this.clearFiberIdsOnLink(links);
                this.clearFiberIdsOnLink(linkMap.values());
            }
        } // synchronized
    } // end method

    // 请求链路上的信息
    private void clearFiberIdsOnLink(Collection<BasicLink> links) throws BaseException {
        if (null != links) {
            for (BasicLink link : links) {
                clearFiberLinkIds(link);
            }
        }
    }

    //  清理当前链路的所有承载的 ID
    private void clearFiberLinkIds(BasicLink sourceLink) throws BaseException {
        LocalVerify.verifyObject(sourceLink, "链路信息不能为空");
        // 获取到原来的信息
        Set<String> fiberLinkIdSet = sourceLink.getFiberLinkIdSet();
        if (null == fiberLinkIdSet) fiberLinkIdSet = new HashSet<>();
        fiberLinkIdSet.clear();
        sourceLink.setFiberLinkIdSet(fiberLinkIdSet);
    }


}
